package com.yuedou.api.pay.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;


public class RSA {
	private static final String ALGORITHM = "RSA";

	private static final String privateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOxwo/w7Yihd7v2L52LEwxhlmX+Fz/YdxXvGXZFoeYquw8N9Qzkg8u9YiVkq8eM0ogha9olJIfQrEfYcKk/1qqg2Ud4sDAz2r+VbzO83z7IEwGxAK7xThaB2aXoukxsKY/0VjKq4oG+h1RF89c8c3membheMIEr4GrtMRuKj16IJAgMBAAECgYEAoXFEN30gx+ljv1Jg+wrZH/Z3uiBXYHjxmFNZHmlU3EH6v6fvV7nMx2sP1YfCRF5y6PubbSA3g+5IxGB078YR8Juw2BJIZP+ZpQsAkYQ8xa0uCmgjhYusJMwFb4JeHrjAN2Zr8Z/YeKg92c2GvXY0RQPrV98JchIwpRvi83T3DIECQQD3/eYgl6/kU5QjQQXTWDWHr4Df2f+CrMrv8TmmtOlpUMSzqYr6RSK0OYYy6Jri1DUSdG+bHl5jHG+hejDW07LxAkEA9BM+w7gCqQaNmDBmGerYv4U/nqRe3iTX+Qtntq7whvomnZrKOvSAJ2EIEbRPABhsh1SIN6nM5A/nCQm3YQywmQJAT7erYTDBlukTBp4hTEXft0VAbTT7gLsg5S6q9J7VJUiUYpiOl1LgDAUt0XGaUG4cvVj2g2uotb1vWP4ZcwVMUQJBAIHhA9MuRewf2pUTnCFKgRBZHaOToA/h1zNlSElECiYpUwcm6Vo55UAPODYDls5cMNRKvTmxl5/8flqm2vg/wnECQQDHDN6jltW6Fo9UI5O4ax+6SQv08ucIJoEc3R9HyIsB4PI4gVd3nVOZjSb95/OYavaU+mied2rDhsMBhOxTZ7wD";

	public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

	private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB";



	/**
	 * 密钥长度 于原文长度对应 以及越长速度越慢
	 */
	private final static int KEY_SIZE = 2048;
	/**
	 * 用于封装随机产生的公钥与私钥
	 */
	private static Map<Integer, String> keyMap = new HashMap<>();


	public class Keys {

	}
	public static final String KEY_ALGORITHM = "RSA";
	//public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
	private static final String PUBLIC_KEY = "RSAPublicKey";
	private static final String PRIVATE_KEY = "RSAPrivateKey";

	/**
	 * RSA验签名检查
	 *
	 * @param content
	 *            待签名数据
	 * @param sign
	 *            签名值
	 * @param input_charset
	 *            编码格式
	 * @return 布尔值
	 */
	public static boolean verify(String content, String sign, String input_charset) {
		try {
			KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
			byte[] encodedKey = Base64.decode(publicKey);
			PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

			java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

			signature.initVerify(pubKey);
			signature.update(content.getBytes(input_charset));
			byte[] arr = Base64.decode(sign);
			if (arr == null) {
				return false;
			}
			boolean bverify = signature.verify(arr);
			return bverify;

		} catch (Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	/**
	 * 解密
	 *
	 * @param content
	 *            密文
	 * @param private_key
	 *            商户私钥
	 * @param input_charset
	 *            编码格式
	 * @return 解密后的字符串
	 */
	public static String decrypt(String content, String private_key, String input_charset) throws Exception {
		PrivateKey prikey = getPrivateKey(private_key);

		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, prikey);

		InputStream ins = new ByteArrayInputStream(Base64.decode(content));
		ByteArrayOutputStream writer = new ByteArrayOutputStream();
		// rsa解密的字节大小最多是128，将需要解密的内容，按128位拆开解密
		byte[] buf = new byte[128];
		int bufl;

		while ((bufl = ins.read(buf)) != -1) {
			byte[] block = null;

			if (buf.length == bufl) {
				block = buf;
			} else {
				block = new byte[bufl];
				for (int i = 0; i < bufl; i++) {
					block[i] = buf[i];
				}
			}

			writer.write(cipher.doFinal(block));
		}

		return new String(writer.toByteArray(), input_charset);
	}

	/**
	 * 得到私钥
	 *
	 * @param key
	 *            密钥字符串（经过base64编码）
	 * @throws Exception
	 */
	public static PrivateKey getPrivateKey(String key) throws Exception {

		byte[] keyBytes;

		keyBytes = Base64.decode(key);

		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

		KeyFactory keyFactory = KeyFactory.getInstance("RSA");

		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

		return privateKey;
	}

	/**
	 *  微信支付退款解密 方法
	 * @param reqInfo
	 * @param api_key
	 * @return
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchProviderException
	 * @throws InvalidKeyException
	 * @throws BadPaddingException
	 * @throws IllegalBlockSizeException
	 */
	public static String descrypt(String reqInfo,String api_key) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
		byte[] reqInfoB = Base64.decode(reqInfo);
		String key_ = DigestUtils.md5Hex(api_key).toLowerCase();

		if (Security.getProvider("BC") == null){
			Security.addProvider(new BouncyCastleProvider());
		}
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
		SecretKeySpec secretKeySpec = new SecretKeySpec(key_.getBytes(), "AES");
		cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
		return new String(cipher.doFinal(reqInfoB));
	}


	//获得公钥
	public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
		//获得map中的公钥对象 转为key对象
		Key key = (Key) keyMap.get(PUBLIC_KEY);
		//byte[] publicKey = key.getEncoded();
		//编码返回字符串
		return encryptBASE64(key.getEncoded());
	}

	//获得私钥
	public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
		//获得map中的私钥对象 转为key对象
		Key key = (Key) keyMap.get(PRIVATE_KEY);
		//byte[] privateKey = key.getEncoded();
		//编码返回字符串
		return encryptBASE64(key.getEncoded());
	}

	//解码返回byte
	public static byte[] decryptBASE64(String key) throws Exception {
		return (new BASE64Decoder()).decodeBuffer(key);
	}

	//编码返回字符串
	public static String encryptBASE64(byte[] key) throws Exception {
		return (new BASE64Encoder()).encodeBuffer(key);
	}

	//map对象中存放公私钥
	public static Map<String, Object> initKey() throws Exception {
		//获得对象 KeyPairGenerator 参数 RSA 1024个字节
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
		keyPairGen.initialize(1024);
		//通过对象 KeyPairGenerator 获取对象KeyPair
		KeyPair keyPair = keyPairGen.generateKeyPair();

		//通过对象 KeyPair 获取RSA公私钥对象RSAPublicKey RSAPrivateKey
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
		//公私钥对象存入map中
		Map<String, Object> keyMap = new HashMap<String, Object>(2);
		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);
		return keyMap;
	}

	public static void main(String[] args) {

//		String content = "OFGD+dpjkMAaIjqJJNky4JlB2l6+MxP0etUbXPlw7/LOZQtBhyq0l+e9VQ++aeE5MKBJ+chRUBjDp2Zte0vtRXrTh4mgw6uvYaE9MaTex6pFQynM5f7T1593XoktDekJ4VlO5S37fzCT5ZdDLwMr6PnnPwi9XpvD31M1UZjlqeS4S6Sn/h2aX+RhL7q9ixuLaBHDYDHx1lyhjKw9IaNshqb0pdD0LlURtIOOaDT4gW6IXXHoZmdEBCpWGcopGPWCXSm4/OJjppdTuyJCOoCkJuP3k1meBBHipkcZm6HB7hPhairokFri9nkz2nUmeZBc+fcxGOWO6rhBXnjKLBZIiJOej0LgAgSDQ8ghNmTrX93IWiKgfgm1sK8uo3am1nlD0mfSpmf+tDvXX+GN+MmnvoUe4FWBPf7qrdg2nIelKJcZCZkbjs2CzWJNHMkaON8vT8/M7PNUnLRcaht3XsHumCtxSsHqAabXDmIHHe+JGU1Kks8N/gyfQsgIeoDaExjV+rXQNHQe2CBBkF1dxiEjPxxynolOR1UT8MjvIwkHdrdojz3Aqde2UrdNkKxfHzVe6BkY+6Wqi3JwtgmcsQ6nnQSvtxk+YuDchf4hn7KhfuxdLuteZQrR3SplOq+F/5dp9AZQeJNOZ0i6TR9qiEcdzygFec8zFO78oD/g77hDP9WwW+dcp7dHm5tX2sfnEDz3eWf/izGhBaduHTSRM9q9OcR4BkO+b9H6ezCLEPLNeJyxpjB0s6wgurCMnbr1BrE3Ffb3Olh4U4oea64yLXV+JrK4b9eUxpNUCkH8VKH7b73kx/bJIP/IkDBResv1CC7hDCjbuXHhRaIassExeH877CbOaIXbHQ211L7kHMMY/Fc3CNgDm4cklpBWm8VU7eMwlMqhAm4NNKHeNrFH2sjE5O5Q9jMrkRuAX7B3WBs3gCZLlTktbpxLZGXUipcRMtMzO04d3ikjrbI3dvlO6u8yp+RjKteezGbJvfgrHPFrSfBtL2GrrFV189XryIB381j41l0GXE/tDb5sRXI5WqTuuMUGDAZlZttGyNyWN3dIgPQ=";
//		String key = "08812c066d6568543ee5b76c4cafd148";
//		try {
//			String decrypt = descrypt(content,"08812c066d6568543ee5b76c4cafd148");
//			Map<String,String> reqInfoMap = WXPayCommonUtil.doXMLParse(decrypt);
//			System.out.println("decrypt:  " + reqInfoMap.toString());
//		} catch (Exception e) {
//			e.printStackTrace();
//		}

		Map<String, Object> keyMap;
		try {
			keyMap = initKey();
			String publicKey = getPublicKey(keyMap);
			System.out.println(" 公钥： " + publicKey);
			String privateKey = getPrivateKey(keyMap);
			System.out.println(" 私钥： " + privateKey);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}
